import {Body, Controller, Get, Post, Record} from "../decorators/common";
import HttpSuccessExpression from "../exceptions/HttpSuccessExpression";
import {authModel} from "../mongoose/model";
import {AuthModelType} from "../mongoose/modelType/type";
import {
  CurrentUser,
  OperationType,
  RecordModule,
  RequestMethod,
  responseMessageMap,
  responseStatusMap as status
} from "../utils";
import {createRecordObj, RecordObj} from "../record";
import {HydratedDocument} from "mongoose";

const message = responseMessageMap.roleController;

@Controller("/api")
export default class RoleController {

  @Get("/roleList")
  public async getRoleList() {
    const result = await authModel.find({roleName: {"$ne": ""}}, {}) as AuthModelType[];
    let roleList: any[] = [];
    if (result) {
      roleList = result.map(role => {
        return {
          roleName: role.roleName,
          createTime: role.createTime,
          authName: role.authName,
          authTime: role.authTime,
          roleList: role.roleList,
          roleId: role._id,
          status: role.status,
          roleDesc: role.roleDesc
        };
      });
    }
    return new HttpSuccessExpression(status.success, message.getRoleListSuccess, {roleList});
  }

  @Post("/addRole")
  @Record(RecordModule.ROLE)
  public async addRole(
    @Body([{name: "roleName", required: true}]) roleInfo: AuthModelType,
    @Body([{name: "username", required: true}, {name: "userId", required: true}]) currentUser: CurrentUser) {
    const newRole = await authModel.create<AuthModelType>(roleInfo) as HydratedDocument<AuthModelType, any, any>;
    const roleId = newRole._doc._id;
    const roleData = delete newRole._doc.__v && newRole._doc;
    const record: RecordObj = {
      operator: currentUser.username,
      operatorId: currentUser.userId,
      operationType: OperationType.CREATE,
      requestMethod: RequestMethod.POST,
      newRecord: Object.assign({}, {roleId}, roleData)
    };
    return new HttpSuccessExpression(status.success, message.addSuccess, {
      role: Object.assign({}, {roleId}, roleData)
    }, createRecordObj(record));
  }

  @Post("/updateRole")
  @Record(RecordModule.ROLE)
  public async updateRole(
    @Body([{name: "roleId", required: true}]) roleInfo: AuthModelType,
    @Body([{name: "username", required: true}, {name: "userId", required: true}]) currentUser: CurrentUser
  ) {
    let oldRole = await authModel.findByIdAndUpdate(roleInfo.roleId, roleInfo, {lean: true}) as AuthModelType;

    const roleId = oldRole._id;
    const oldRoleData = delete (oldRole as any).__v && oldRole;

    const record: RecordObj = {
      operator: currentUser.username,
      operatorId: currentUser.userId,
      operationType: OperationType.UPDATE,
      requestMethod: RequestMethod.POST,
      oldRecord: Object.assign({}, {roleId, ...oldRoleData}),
      newRecord: Object.assign({}, {roleId, ...roleInfo})
    };
    return new HttpSuccessExpression(status.success, message.updateSuccess, {
      role: Object.assign({}, {roleId, ...roleInfo})
    }, createRecordObj(record));
  }

  @Post("/deleteRole")
  @Record(RecordModule.ROLE)
  public async deleteRole(
    @Body() roleId: string,
    @Body([{name: "username", required: true}, {name: "userId", required: true}]) currentUser: CurrentUser
  ) {
    let deleteRole = await authModel.findByIdAndDelete<AuthModelType>({_id: roleId}, {new: true, lean: true});
    const deleteRoleId = deleteRole!._id;
    const roleData = delete (deleteRole as any).__v && deleteRole;

    const record: RecordObj = {
      operator: currentUser.username,
      operatorId: currentUser.userId,
      operationType: OperationType.DELETE,
      requestMethod: RequestMethod.POST,
      oldRecord: Object.assign({}, {roleId: deleteRoleId}, roleData)
    };
    return new HttpSuccessExpression(status.success, message.deleteSuccess, {
      role: Object.assign({}, {roleId: deleteRoleId}, roleData)
    }, createRecordObj(record));
  }
}